<template>
  <template v-if="isEditor">
    <div class="vc-relative vc-flex-1 vc-h-full vc-overflow-hidden" @dragover="legendGragover" @drop="legendDrop">
      <div class="vc-h-full vc-overflow-auto">
        <MainSvg :box-select="boxSelect" @mousedown="startSelect" />
      </div>
      <Zoom v-model="scaleFactor" class="vc-absolute vc-left-2 vc-bottom-6" />
    </div>
    <div class="vc-border-l vc-border-gray-300 vc-w-60 vc-bg-white vc-flex vc-flex-col">
      <div class="vc-flex vc-flex-row vc-items-stretch vc-border-b vc-border-solid vc-border-gray-200 vc-text-center">
        <div
          class="
            vc-flex-1 vc-py-4 vc-border-r vc-border-solid vc-border-gray-200 vc-cursor-pointer
            hover:vc-bg-gray-100
          "
          :class="{ '!vc-bg-blue-500 vc-text-white': curIndex === 0 }"
          @click="curIndex = 0"
        >
          属性面板
        </div>
        <div
          class="vc-flex-1 vc-py-4 vc-cursor-pointer hover:vc-bg-gray-100"
          :class="{ '!vc-bg-blue-500 vc-text-white': curIndex === 1 }"
          @click="curIndex = 1"
        >
          条件面板
        </div>
      </div>
      <div class="vc-flex-1 vc-overflow-auto">
        <AttrPanel
          v-show="curIndex === 0"
          :cur-select-data="curSelectData"
          :update-panel-options="updatePanelOptions"
        />
        <ConditionPanel v-show="curIndex === 1" ref="conditionalPanelEl" :cur-select-data="curSelectData" />
      </div>
    </div>
  </template>
  <MainSvg v-else ref="mainSvgIns" />
</template>
<script setup lang="ts">
import { inject, ref, watch, provide, onMounted, shallowRef, nextTick } from "vue";
import { useSelect } from "./useSelect";
import {
  ContextmenuItem,
  SvgInfo,
  GridLineExpose,
  RootCommon,
  ConfigurationEl,
  ConfigurationType,
  ConditionalPanelExpose,
  MainSvgExpose,
} from "./types";
import { RootCommonKey } from "./types";
import { UpdatePanelOptions } from "./AttrPanel/types";
import { insterAfter } from "/@/utils/dom";
import { CompCommon, CompCommonKey, LabelValueJSON } from "/@/components/types";
import { buildShortUUID } from "/@/utils/uuid";
import { FlowPathLegendSize } from "/@/components/common";
import { useData } from "./useData";
import AttrPanel from "./AttrPanel/AttrPanel.vue";
import ConditionPanel from "./ConditionPanel/ConditionPanel.vue";
import MainSvg from "./MainSvg.vue";
import Zoom from "/@/components/base/Zoom.vue";
import { useMagicKeys } from "@vueuse/core";

const props = defineProps<{
  showContextmenu: (e: MouseEvent | null, data?: ContextmenuItem[]) => void;
  compData?: any;
  isEditor: boolean;
}>();

const emits = defineEmits(["load"]);

const isEditor = ref(props.isEditor);
watch(
  () => props.isEditor,
  (v) => {
    isEditor.value = v;
  }
);

const {
  deviceSvgData,
  deviceImageData,
  pipePathData,
  labelValueData,
  compInstance,
  connection,
  scaleFactor,
  pipePathLegendData,
  deviceImageLegendData,
  deviceSvgLegendData,
  flowPathData,
  flowPathLegendData,
} = inject(RootCommonKey) as RootCommon;

/**
 * add sub component instance
 */
function legendGragover(e: DragEvent) {
  e.preventDefault();
}
function legendDrop(e: DragEvent) {
  if (e.dataTransfer) {
    const type = e.dataTransfer.getData("type");
    const i = +e.dataTransfer.getData("index");
    if (type === ConfigurationType.PipePath) {
      addPath(e, i);
    } else if (type === ConfigurationType.DeviceImage) {
      addImg(e, i);
    } else if (type === ConfigurationType.DeviceSvg) {
      addSvg(e, i);
    } else if (type === ConfigurationType.LabelValue) {
      addLabelValue(e);
    } else if (type === ConfigurationType.FlowPath) {
      addFlowPath(e, i);
    }
  }
}
//PipePath
function addPath(e: DragEvent, i: number) {
  const target = pipePathLegendData.value[i];
  pipePathData.value.push({
    id: buildShortUUID(ConfigurationType.PipePath),
    centerX: e.offsetX,
    centerY: e.offsetY,
    colors: target.colors,
    pipePathType: target.type,
  });
}
//DeviceImage
function addImg(e: DragEvent, i: number) {
  deviceImageData.value.push({
    id: buildShortUUID(ConfigurationType.DeviceImage),
    centerX: e.offsetX,
    centerY: e.offsetY,
    imgSrc: deviceImageLegendData.value[i].src,
    imgName: deviceImageLegendData.value[i].name,
  });
}
//DeviceSvg
function addSvg(e: DragEvent, i: number) {
  deviceSvgData.value.push({
    id: buildShortUUID(ConfigurationType.DeviceSvg),
    centerX: e.offsetX,
    centerY: e.offsetY,
    componentName: deviceSvgLegendData.value[i].name,
    initWidth: deviceSvgLegendData.value[i].width,
  });
}
//LabelValue
function addLabelValue(e: DragEvent) {
  labelValueData.value.push({
    id: buildShortUUID(ConfigurationType.LabelValue),
    centerX: e.offsetX,
    centerY: e.offsetY,
  });
}
//FlowPath
function addFlowPath(e: DragEvent, i: number) {
  flowPathData.value.push({
    id: buildShortUUID(ConfigurationType.FlowPath),
    centerX: e.offsetX,
    centerY: e.offsetY,
    initWidth: FlowPathLegendSize.width * 2,
    initHeight: FlowPathLegendSize.height * 2,
    flowPathType: flowPathLegendData.value[i].type,
  });
}

//删除后 触发组件各自的onBeforeUnmount，解除连接关系
function deleteCompItem(id: string) {
  let data: ConfigurationEl[];
  if (id.startsWith(ConfigurationType.DeviceImage)) {
    data = deviceImageData.value;
  } else if (id.startsWith(ConfigurationType.DeviceSvg)) {
    data = deviceSvgData.value;
  } else if (id.startsWith(ConfigurationType.LabelValue)) {
    data = labelValueData.value;
  } else if (id.startsWith(ConfigurationType.PipePath)) {
    data = pipePathData.value;
  } else {
    data = flowPathData.value;
  }
  const index = data.findIndex((el) => el.id === id);
  if (index !== -1) {
    data.splice(index, 1);
  }
}

/**
 * 画布
 */
const svgEl = shallowRef<HTMLElement | null>(null);
const boxSelectEl = shallowRef<SVGRectElement | null>(null);
const gridLineIns = shallowRef<GridLineExpose | null>(null);
const initSvgInfo: CompCommon["initSvgInfo"] = (e) => {
  svgEl.value = e.svgEl;
  boxSelectEl.value = e.boxSelectEl;
  gridLineIns.value = e.gridLineIns;
};
function getSvgInfo(): SvgInfo | undefined {
  if (svgEl.value) {
    const rect = svgEl.value.getBoundingClientRect();
    return {
      width: rect.width,
      height: rect.height,
      element: svgEl.value,
      container: svgEl.value.parentNode as HTMLDivElement,
    };
  } else {
    console.error("svg element is not init");
  }
}
//svg元素置顶方法
function toTop(el: SVGElement) {
  if (svgEl.value && boxSelectEl.value) {
    svgEl.value.insertBefore(el, boxSelectEl.value);
  }
}
//svg元素置底方法
function toBottom(el: SVGElement) {
  if (gridLineIns.value) {
    insterAfter(el, gridLineIns.value.getEl());
  }
}
/**
 * 初始化选择模块
 */
const { toggleSelect, startSelect, boxSelect, multipleSelect, curSelectData } = useSelect({
  connection,
  compInstance,
  onMousedown() {
    props.showContextmenu(null);
  },
  getSvgInfo,
  isEditor,
});
/**
 * 右击设备事件
 */
const showContextmenu: CompCommon["showContextmenu"] = (e, { data, id, element }) => {
  if (!data) {
    data = [];
  }
  if (id && element) {
    if (data.length > 0) {
      data.push({ split: true });
    }
    data = data.concat([
      {
        name: "删除",
        handler() {
          deleteCompItem(id);
        },
      },
      {
        name: "置顶",
        handler() {
          toTop(element);
        },
      },
      {
        name: "置底",
        handler() {
          toBottom(element);
        },
      },
    ]);
  }
  if (data.length === 0) return;
  e.preventDefault();
  e.stopPropagation();
  props.showContextmenu(e, data);
};

/**
 * panel
 */
const updatePanelOptions = ref<UpdatePanelOptions<any>>();
function updatePanelInfo(options: UpdatePanelOptions<any>) {
  updatePanelOptions.value = options;
}
const conditionalPanelEl = ref<ConditionalPanelExpose | null>(null);
const curIndex = ref(0);
watch(curIndex, (v) => {
  if (v === 1) {
    conditionalPanelEl.value?.refresh();
  }
});
/**
 * provide common to sub components
 */
provide(CompCommonKey, {
  getSvgInfo,
  connection,
  deleteCompItem,
  showContextmenu,
  toggleSelect,
  multipleSelect,
  updatePanelInfo,
  isEditor,
  toTop,
  initSvgInfo,
});
//编辑模式下 监听键盘按键
if (isEditor.value) {
  const keys = useMagicKeys();
  const ctrlC = keys["Ctrl+C"];
  watch(ctrlC, (v) => {
    if (v && curSelectData.length === 1) {
      //暂时只能复制单个LabelValue
      const item = curSelectData[0];
      if (item.type === ConfigurationType.LabelValue) {
        const ins = compInstance[item.id as string];
        if (ins) {
          const json = ins.toJSON() as LabelValueJSON;
          const newId = buildShortUUID(ConfigurationType.LabelValue);
          labelValueData.value.push({
            id: newId,
            centerX: 0,
            centerY: 0,
          });
          nextTick(() => {
            const ins = compInstance[newId];
            if (ins) {
              json.labelX -= 20;
              json.labelY -= 20;
              ins.setJSON(json);
            }
          });
        }
      }
    }
  });
}
//加载传入Configuration的组件数据
async function loadCompData() {
  if (props.compData) {
    const { importData } = useData();
    await importData(props.compData);
    emits("load");
    mainSvgIns.value?.initViewBox();
  }
}
const mainSvgIns = ref<MainSvgExpose>();
onMounted(() => {
  watch(() => props.compData, loadCompData, {
    immediate: true,
  });
});
</script>
